package tests;

import static org.junit.Assert.*;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import paydayTransaction.PaydayTransaction;

import main.Paycheck;
import methods.HoldMethod;
import methods.PaymentMethod;
import salesReceiptTransaction.SalesReceiptTransaction;
import schedule.BiWeeklySchedule;
import schedule.MonthlySchedule;
import schedule.PaymentSchedule;
import schedule.Period;
import schedule.WeeklySchedule;
import serviceChargeTransaction.ServiceCharge;
import serviceChargeTransaction.ServiceChargeTransaction;
import addEmployeeTransaction.AddCommissionedEmployee;
import addEmployeeTransaction.AddHourlyEmployee;
import addEmployeeTransaction.AddSalariedEmployee;
import addEmployeeTransaction.Employee;
import affiliation.UnionAffiliation;
import classification.CommissionClassification;
import classification.HourlyClassification;
import classification.PaymentClassification;
import classification.SalariedClassification;
import database.InMemoryPayrollDatabase;
import database.PayrollDatabase;
import deleteEmployeeTransaction.DeleteEmployeeTransaction;

public class TestEmployee {
	InMemoryPayrollDatabase database = null;
	
	@Before
	public void initialize() {
		database = InMemoryPayrollDatabase.getInstance();
	}
	
	@After
	public void breakDown() {
		database = null;
	}
	
	@Test
	public void testAddSalariedEmployee() {
				
		int empId = 1;
		AddSalariedEmployee t =
			new AddSalariedEmployee(empId, "Bob", "Home", 1000.00, database);
		t.execute();

		Employee e = database.getEmployee(empId);
		assertEquals("Bob", e.getName());

		PaymentClassification pc = e.getClassification();
		assertTrue(pc instanceof SalariedClassification);
		SalariedClassification sc = (SalariedClassification) pc;

		assertEquals(1000.00, sc.getSalary(), .001);
		PaymentSchedule ps = e.getSchedule();
		assertTrue(ps instanceof MonthlySchedule);

		PaymentMethod pm = e.getMethod();
		assertTrue(pm instanceof HoldMethod);
	}
	
	@Test
	public void testAddHourlyEmployee() {
		int empId = 2;
		AddHourlyEmployee t =
			new AddHourlyEmployee(empId, "Micah", "Home", 200.00, database);
		t.execute();
	
		Employee e = database.getEmployee(empId);
		assertEquals("Micah", e.getName());
	
		PaymentClassification pc = e.getClassification();
		assertTrue(pc instanceof HourlyClassification);
		HourlyClassification hc = (HourlyClassification) pc;
	
		assertEquals(200.00, hc.getHourlyRate(), .001);
		PaymentSchedule ps = e.getSchedule();
		assertTrue(ps instanceof WeeklySchedule);
	
		PaymentMethod pm = e.getMethod();
		assertTrue(pm instanceof HoldMethod);
	}
	
	@Test
	public void TestAddCommissionedEmployee() {
		int empId = 3;
		AddCommissionedEmployee t =
			new AddCommissionedEmployee(empId, "Justin", "Home", 2500, 9.5, database);
		t.execute();

		Employee e = database.getEmployee(empId);
		assertEquals("Justin", e.getName());

		PaymentClassification pc = e.getClassification();
		assertTrue(pc instanceof CommissionClassification);
		CommissionClassification cc = (CommissionClassification) pc;

		assertEquals(2500, cc.getBaseRate(), .001);
		assertEquals(9.5, cc.getCommissionRate(), .001);
		PaymentSchedule ps = e.getSchedule();
		assertTrue(ps instanceof BiWeeklySchedule);

		PaymentMethod pm = e.getMethod();
		assertTrue(pm instanceof HoldMethod);
	}
	
	@Test
	public void DeleteEmployee() {
		int empId = 4;
		AddCommissionedEmployee t =
			new AddCommissionedEmployee(
				empId, "Bill", "Home", 2500, 3.2, database);
		t.execute();

		Employee e = database.getEmployee(empId);
		assertNotNull(e);

		DeleteEmployeeTransaction dt =
			new DeleteEmployeeTransaction(empId, database);
		dt.execute();

		e = database.getEmployee(empId);
		assertNull(e);
	}
	
	@Test
	@SuppressWarnings("deprecation")
	public void AddServiceCharge() {
		int empId = 2;
		AddHourlyEmployee t = new AddHourlyEmployee(
			empId, "Bill", "Home", 15.25, database);
		t.execute();
		Employee e = database.getEmployee(empId);
		assertNotNull(e);
		UnionAffiliation af = new UnionAffiliation();
		e.setAffiliation(af);
		int memberId = 86; // Maxwell Smart
		database.addUnionMember(memberId, e);
		ServiceChargeTransaction sct =
			new ServiceChargeTransaction(
				memberId, new Timestamp(2005, 8, 8, 0, 0, 0, 0), 12.95, database);
		try {
			sct.execute();
		} catch (Exception e1) {
			fail("sct.execute() throws an Exception");
		}
		ServiceCharge sc =
			af.getServiceCharge(new Timestamp(2005, 8, 8, 0, 0, 0, 0));
		assertNotNull(sc);
		assertEquals(12.95, sc.getAmount(), .001);
	}
}